從安裝webpack理解react與react-dom(without JSX)這篇實作了打包react,這篇會延續其部分並編譯jsx
另外也會介紹以下部分
從安裝webpack理解react與react-dom(without JSX)的文章內容在createElement的解釋並沒有多作探討,因此這裡解釋一下createElement函式的參數。
依據官方文檔React Top-Level API-createelement
createElement可以接受參數如下
React.createElement(
type,
[props],
[...children]
)
type指的是tag的名字,例如'div','h1'等等,第二個參數參數是props,其內容例如HTML的屬性id=animal,第三個參數是children,這裡使用...表示children可以不僅是一個,下面範例延續昨天範例,這次多加了屬性為style,其value也是一個物件,其物件的屬性是color、值為紅色。
import React from "react";
const App = () => {
return React.createElement("h1",
{
style: {
color: "red",
},
}, "我是H1");
//第一個參數是tag名稱,第二個是prop、第三個是內容
};
透過console的方式React.createElement的回傳值可以看到如下
透過瀏覽器除錯工具打開上面的語法最後react-dom會幫我們渲染成如下的內容
我們如果今天要渲染h1內容有"我是h1"的話,react其實就是以props.children來渲染,因此如果希望有子元素像是無序清單<ul>
裡面有li
也可以用同樣的方式渲染。則可以在createElement第三個參數後帶入。
觀看以下的程式碼
import React from "react";
const App = () => {
const list = React.createElement(
"ul",
{
style: {
color: "red",
},
},
React.createElement("li", null, "Dog"),
React.createElement("li", null, "Cat"),
React.createElement("li", null, "Fish")
);
console.log(list);
return list;
};
export default App;
打包完畢後應當可以看到如下圖
我們最後也可以console查看最後react元素的內容是什麼,如下圖。
可以發現當children不只一個的時候,他會變成陣列的形式成為react 元素。
由上述程式碼可以發現假如我們需要建構一個大型應用程式,其包含許多標籤的時候程式碼會過於複雜,因此勢必要衍生出一種新的撰寫模式—jsx。
根據facebook的github解釋jsx的spec其大致描述是一種類似於XML的javascript語法擴充,但他不會納入ECMAscript的spec,因此需要透過預處理器轉譯。
在選用jsx前也有考量到Template literals樣板字面值的方式如何,但是閱讀性也不佳,另外也可能導致一些建置工具將可能無法作用。
另外也有考慮使用JXON的做法,但是也因為語法提示不佳,因此最後jsx成為了多數人撰寫react的方式。
Babel工具是一套能夠將Javascript新語法轉譯成與某個舊版本的瀏覽器相容的工具,例如我們如果用ES6以上的語法,然而在一些舊的瀏覽器當中並不能夠理解這些Javascript的新語法,因此我們透過babel將新語法轉換成舊語法或是使用Polyfill的方式來實現在舊的瀏覽器運行。
需要編譯jsx的話,事前得安裝core和preset-env,一個是babel的核心,另外一個是轉換舊語法的工具npm install @babel/core @babel/preset-env --save-dev
另外由於要給webpack需要讀懂babel,想當然而也需要loader,因此輸入以下指令安裝babel loadernpm install babel-loader --save-dev
最後是要編譯成jsx的工具(備註)。npm install @babel/preset-react --save-dev
備註:其內容其實包含許多plugin,有興趣的人可以點該連結
安裝完畢後設定webpack.config.js
如下
const path = require("path");
module.exports = {
entry: "/src/index.js",
output: { path: path.resolve(__dirname, "dist") },
module: {
rules: [
{
test: /\.(js|jsx)$/,//正則表達式取副檔名是js/jsx
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: { presets: ["@babel/preset-env", "@babel/preset-react"] },
},
},
],
},
};
上面設定意思是將副檔名為js或jsx的檔案透過babel-loader載入後使用preset-env和preset-react編譯。
App.js的內容如下
import React from "react";
const App = () => {
return <div>測試</div>;
};
export default App;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script src="./main.js"></script>
</body>
</html>
其資料夾結構應當如下
最後再npm run build
應當可以如期的得到打包後的js檔案。
我們也就成功編譯了jsx了。如下圖
本篇講解了createElement的函式,其中提到了props和children,當我們實際在使用react的時候會很常使用這兩個屬性,另外也淺談使用了jsx的原因,透過實作webpack編譯jsx的過程也提及了bebal的用途,最後Babel有提供一個線上觀看轉譯後的程式碼的網頁連結在此,左邊勾選react和LineWrap就可以看到轉譯後的結果了。
希望這篇文章能對大家有所幫助以上